Skip to content

Conversation

cor3ntin
Copy link
Contributor

@cor3ntin cor3ntin commented Oct 2, 2025

@cor3ntin cor3ntin requested review from Endilll and a team as code owners October 2, 2025 13:53
@llvmbot llvmbot added clang Clang issues not falling into any other category libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules HLSL HLSL Language Support labels Oct 2, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 2, 2025

@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-modules

@llvm/pr-subscribers-libcxx

Author: Corentin Jabot (cor3ntin)

Changes

Reverts llvm/llvm-project#141776

CI failures

https://lab.llvm.org/buildbot/#/builders/202/builds/3591
https://lab.llvm.org/buildbot/#/builders/55/builds/18066
https://lab.llvm.org/buildbot/#/builders/85/builds/14103


Patch is 266.00 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/161669.diff

50 Files Affected:

  • (modified) clang/docs/InternalsManual.rst (-61)
  • (modified) clang/docs/ReleaseNotes.rst (-4)
  • (modified) clang/include/clang/AST/ASTConcept.h (+12-21)
  • (modified) clang/include/clang/AST/ASTContext.h (+1)
  • (modified) clang/include/clang/Sema/Sema.h (+41-64)
  • (modified) clang/include/clang/Sema/SemaConcept.h (+79-355)
  • (modified) clang/include/clang/Sema/Template.h (+9-13)
  • (modified) clang/lib/AST/ASTConcept.cpp (+6-25)
  • (modified) clang/lib/AST/ASTImporter.cpp (+6-6)
  • (modified) clang/lib/Sema/SemaConcept.cpp (+703-1309)
  • (modified) clang/lib/Sema/SemaDeclCXX.cpp (+7-9)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+6-10)
  • (modified) clang/lib/Sema/SemaOverload.cpp (+1-2)
  • (modified) clang/lib/Sema/SemaTemplate.cpp (+32-61)
  • (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+15-36)
  • (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+53-116)
  • (modified) clang/lib/Sema/TreeTransform.h (+10-9)
  • (modified) clang/lib/Serialization/ASTReaderDecl.cpp (+1-1)
  • (modified) clang/lib/Serialization/ASTReaderStmt.cpp (+5-9)
  • (modified) clang/lib/Serialization/ASTWriterStmt.cpp (+6-12)
  • (modified) clang/test/AST/ast-dump-concepts.cpp (+4-6)
  • (modified) clang/test/AST/ast-dump-ctad-alias.cpp (+10-11)
  • (modified) clang/test/CXX/drs/cwg25xx.cpp (+6-8)
  • (modified) clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp (+1-2)
  • (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp (+7-7)
  • (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp (+20-15)
  • (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp (+2-2)
  • (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp (+6-6)
  • (modified) clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp (+3-2)
  • (modified) clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp (+17-42)
  • (modified) clang/test/CXX/temp/temp.param/p10-2a.cpp (+10-13)
  • (modified) clang/test/SemaCXX/cxx23-assume.cpp (+5-4)
  • (modified) clang/test/SemaCXX/cxx2b-deducing-this.cpp (+4-4)
  • (modified) clang/test/SemaCXX/cxx2c-fold-exprs.cpp (+40-162)
  • (modified) clang/test/SemaCXX/cxx2c-template-template-param.cpp (+2-2)
  • (modified) clang/test/SemaCXX/invalid-requirement-requires-expr.cpp (+2-2)
  • (modified) clang/test/SemaCXX/overload-resolution-deferred-templates.cpp (+2-1)
  • (modified) clang/test/SemaCXX/type-traits.cpp (+2-2)
  • (modified) clang/test/SemaHLSL/BuiltIns/Buffers.hlsl (+3-3)
  • (modified) clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl (+3-3)
  • (modified) clang/test/SemaTemplate/concepts-recovery-expr.cpp (+11-21)
  • (modified) clang/test/SemaTemplate/concepts-recursive-inst.cpp (+13-14)
  • (modified) clang/test/SemaTemplate/concepts.cpp (+8-63)
  • (modified) clang/test/SemaTemplate/deduction-guide.cpp (+6-9)
  • (modified) clang/test/SemaTemplate/instantiate-abbreviated-template.cpp (-1)
  • (modified) clang/test/SemaTemplate/instantiate-expanded-type-constraint.cpp (+2-2)
  • (modified) clang/test/SemaTemplate/instantiate-requires-expr.cpp (+5-15)
  • (modified) clang/test/SemaTemplate/instantiate-template-argument.cpp (+7-90)
  • (modified) clang/test/SemaTemplate/pr52970.cpp (+1-1)
  • (modified) libcxx/test/libcxx/algorithms/cpp17_iterator_concepts.verify.cpp (+2-2)
diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst
index c677ddfa5ecc1..bd742273f4ed5 100644
--- a/clang/docs/InternalsManual.rst
+++ b/clang/docs/InternalsManual.rst
@@ -2859,67 +2859,6 @@ This library is called by the :ref:`Parser library <Parser>` during parsing to
 do semantic analysis of the input.  For valid programs, Sema builds an AST for
 parsed constructs.
 
-
-Concept Satisfaction Checking and Subsumption
----------------------------------------------
-
-As per the C++ standard, constraints are `normalized <https://eel.is/c++draft/temp.constr.normal>`_
-and the normal form is used both for subsumption, and constraint checking.
-Both depend on a parameter mapping that substitutes lazily. In particular,
-we should not substitute in unused arguments.
-
-Clang follows the order of operations prescribed by the standard.
-
-Normalization happens prior to satisfaction and subsumption
-and is handled by ``NormalizedConstraint``.
-
-Clang preserves in the normalized form intermediate concept-ids
-(``ConceptIdConstraint``) This is used for diagnostics only and no substitution
-happens in a ConceptIdConstraint if its expression is satisfied.
-
-The normal form of the associated constraints of a declaration is cached in
-Sema::NormalizationCache such that it is only computed once.
-
-A ``NormalizedConstraint`` is a recursive data structure, where each node
-contains a parameter mapping, represented by the indexes of all parameter
-being used.
-
-Checking satisfaction is done by ``ConstraintSatisfactionChecker``, recursively
-walking ``NormalizedConstraint``. At each level, we substitute the outermost
-level of the template arguments referenced in the parameter mapping of a
-normalized expression (``MultiLevelTemplateArgumentList``).
-
-For the following example,
-
-.. code-block:: c++
-
-  template <typename T>
-  concept A = __is_same(T, int);
-
-  template <typename U>
-  concept B = A<U> && __is_same(U, int);
-
-The normal form of B is
-
-.. code-block:: c++
-
-    __is_same(T, int) /*T->U, innermost level*/
- && __is_same(U, int) {U->U} /*T->U, outermost level*/
-
-After substitution in the mapping, we substitute in the constraint expression
-using that copy of the ``MultiLevelTemplateArgumentList``, and then evaluate it.
-
-Because this is expensive, it is cached in
-``UnsubstitutedConstraintSatisfactionCache``.
-
-Any error during satisfaction is recorded in ``ConstraintSatisfaction``.
-for nested requirements, ``ConstraintSatisfaction`` is stored (including
-diagnostics) in the AST, which is something we might want to improve.
-
-When an atomic constraint is not satified, we try to substitute into any
-enclosing concept-id using the same mechanism described above, for
-diagnostics purpose, and inject that in the ``ConstraintSatisfaction``.
-
 .. _CodeGen:
 
 The CodeGen Library
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a1e3a0c51d8e1..c6ee1e282a008 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -160,10 +160,6 @@ C++23 Feature Support
 C++20 Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 
-- Clang now normalizes constraints before checking whether they are satisfied, as mandated by the standard.
-  As a result, Clang no longer incorrectly diagnoses substitution failures in template arguments only
-  used in concept-ids, and produces better diagnostics for satisfaction failure. (#GH61811) (#GH135190)
-
 C++17 Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h
index f362f24ebc72a..72da0059744f2 100644
--- a/clang/include/clang/AST/ASTConcept.h
+++ b/clang/include/clang/AST/ASTConcept.h
@@ -28,20 +28,10 @@ namespace clang {
 
 class ConceptDecl;
 class TemplateDecl;
-class ConceptReference;
 class Expr;
 class NamedDecl;
 struct PrintingPolicy;
 
-/// Unsatisfied constraint expressions if the template arguments could be
-/// substituted into them, or a diagnostic if substitution resulted in
-/// an invalid expression.
-///
-using ConstraintSubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
-using UnsatisfiedConstraintRecord =
-    llvm::PointerUnion<const Expr *, const ConceptReference *,
-                       const ConstraintSubstitutionDiagnostic *>;
-
 /// The result of a constraint satisfaction check, containing the necessary
 /// information to diagnose an unsatisfied constraint.
 class ConstraintSatisfaction : public llvm::FoldingSetNode {
@@ -58,13 +48,16 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
                          ArrayRef<TemplateArgument> TemplateArgs)
       : ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs) {}
 
+  using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
+  using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
+
   bool IsSatisfied = false;
   bool ContainsErrors = false;
 
   /// \brief The substituted constraint expr, if the template arguments could be
   /// substituted into them, or a diagnostic if substitution resulted in an
   /// invalid expression.
-  llvm::SmallVector<UnsatisfiedConstraintRecord, 4> Details;
+  llvm::SmallVector<Detail, 4> Details;
 
   void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
     Profile(ID, C, ConstraintOwner, TemplateArgs);
@@ -76,12 +69,19 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
 
   bool HasSubstitutionFailure() {
     for (const auto &Detail : Details)
-      if (Detail.dyn_cast<const ConstraintSubstitutionDiagnostic *>())
+      if (Detail.dyn_cast<SubstitutionDiagnostic *>())
         return true;
     return false;
   }
 };
 
+/// Pairs of unsatisfied atomic constraint expressions along with the
+/// substituted constraint expr, if the template arguments could be
+/// substituted into them, or a diagnostic if substitution resulted in
+/// an invalid expression.
+using UnsatisfiedConstraintRecord =
+    llvm::PointerUnion<Expr *, std::pair<SourceLocation, StringRef> *>;
+
 /// \brief The result of a constraint satisfaction check, containing the
 /// necessary information to diagnose an unsatisfied constraint.
 ///
@@ -101,10 +101,6 @@ struct ASTConstraintSatisfaction final :
     return getTrailingObjects() + NumRecords;
   }
 
-  ArrayRef<UnsatisfiedConstraintRecord> records() const {
-    return {begin(), end()};
-  }
-
   ASTConstraintSatisfaction(const ASTContext &C,
                             const ConstraintSatisfaction &Satisfaction);
   ASTConstraintSatisfaction(const ASTContext &C,
@@ -286,11 +282,6 @@ class TypeConstraint {
   }
 };
 
-/// Insertion operator for diagnostics.  This allows sending ConceptReferences's
-/// into a diagnostic with <<.
-const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
-                                      const ConceptReference *C);
-
 } // clang
 
 #endif // LLVM_CLANG_AST_ASTCONCEPT_H
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 78220d4d8ff5b..12351e98e5a2b 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -3877,6 +3877,7 @@ typename clang::LazyGenerationalUpdatePtr<Owner, T, Update>::ValueType
     return new (Ctx) LazyData(Source, Value);
   return Value;
 }
+
 template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeID> {
   static FoldingSetNodeID getEmptyKey() { return FoldingSetNodeID{}; }
 
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index bd3e042868299..f53aafdeb4f36 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -65,7 +65,6 @@
 #include "clang/Sema/Redeclaration.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaBase.h"
-#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/TypoCorrection.h"
 #include "clang/Sema/Weak.h"
 #include "llvm/ADT/APInt.h"
@@ -11695,9 +11694,8 @@ class Sema final : public SemaBase {
   ExprResult
   CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
                          const DeclarationNameInfo &ConceptNameInfo,
-                         NamedDecl *FoundDecl, TemplateDecl *NamedConcept,
-                         const TemplateArgumentListInfo *TemplateArgs,
-                         bool DoCheckConstraintSatisfaction = true);
+                         NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
+                         const TemplateArgumentListInfo *TemplateArgs);
 
   void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
   void diagnoseMissingTemplateArguments(const CXXScopeSpec &SS,
@@ -12027,13 +12025,6 @@ class Sema final : public SemaBase {
                                  bool UpdateArgsWithConversions = true,
                                  bool *ConstraintsNotSatisfied = nullptr);
 
-  bool CheckTemplateArgumentList(
-      TemplateDecl *Template, TemplateParameterList *Params,
-      SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs,
-      const DefaultArguments &DefaultArgs, bool PartialTemplateArgs,
-      CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions = true,
-      bool *ConstraintsNotSatisfied = nullptr);
-
   bool CheckTemplateTypeArgument(
       TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
       SmallVectorImpl<TemplateArgument> &SugaredConverted,
@@ -12792,18 +12783,6 @@ class Sema final : public SemaBase {
   void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
                                   unsigned Depth, llvm::SmallBitVector &Used);
 
-  /// Mark which template parameters are named in a given expression.
-  ///
-  /// Unlike MarkUsedTemplateParameters, this excludes parameter that
-  /// are used but not directly named by an expression - i.e. it excludes
-  /// any template parameter that denotes the type of a referenced NTTP.
-  ///
-  /// \param Used a bit vector whose elements will be set to \c true
-  /// to indicate when the corresponding template parameter will be
-  /// deduced.
-  void MarkUsedTemplateParametersForSubsumptionParameterMapping(
-      const Expr *E, unsigned Depth, llvm::SmallBitVector &Used);
-
   /// Mark which template parameters can be deduced from a given
   /// template argument list.
   ///
@@ -12820,9 +12799,6 @@ class Sema final : public SemaBase {
   void MarkUsedTemplateParameters(ArrayRef<TemplateArgument> TemplateArgs,
                                   unsigned Depth, llvm::SmallBitVector &Used);
 
-  void MarkUsedTemplateParameters(ArrayRef<TemplateArgumentLoc> TemplateArgs,
-                                  unsigned Depth, llvm::SmallBitVector &Used);
-
   void
   MarkDeducedTemplateParameters(const FunctionTemplateDecl *FunctionTemplate,
                                 llvm::SmallBitVector &Deduced) {
@@ -13120,9 +13096,6 @@ class Sema final : public SemaBase {
     /// Whether we're substituting into constraints.
     bool InConstraintSubstitution;
 
-    /// Whether we're substituting into the parameter mapping of a constraint.
-    bool InParameterMappingSubstitution;
-
     /// The point of instantiation or synthesis within the source code.
     SourceLocation PointOfInstantiation;
 
@@ -13386,11 +13359,6 @@ class Sema final : public SemaBase {
                          const MultiLevelTemplateArgumentList &TemplateArgs,
                          TemplateArgumentListInfo &Outputs);
 
-  bool SubstTemplateArgumentsInParameterMapping(
-      ArrayRef<TemplateArgumentLoc> Args, SourceLocation BaseLoc,
-      const MultiLevelTemplateArgumentList &TemplateArgs,
-      TemplateArgumentListInfo &Out, bool BuildPackExpansionTypes);
-
   /// Retrieve the template argument list(s) that should be used to
   /// instantiate the definition of the given declaration.
   ///
@@ -13852,12 +13820,6 @@ class Sema final : public SemaBase {
            CodeSynthesisContexts.back().InConstraintSubstitution;
   }
 
-  bool inParameterMappingSubstitution() const {
-    return !CodeSynthesisContexts.empty() &&
-           CodeSynthesisContexts.back().InParameterMappingSubstitution &&
-           !inConstraintSubstitution();
-  }
-
   using EntityPrinter = llvm::function_ref<void(llvm::raw_ostream &)>;
 
   /// \brief create a Requirement::SubstitutionDiagnostic with only a
@@ -14742,10 +14704,6 @@ class Sema final : public SemaBase {
     SatisfactionStack.swap(NewSS);
   }
 
-  using ConstrainedDeclOrNestedRequirement =
-      llvm::PointerUnion<const NamedDecl *,
-                         const concepts::NestedRequirement *>;
-
   /// Check whether the given expression is a valid constraint expression.
   /// A diagnostic is emitted if it is not, false is returned, and
   /// PossibleNonPrimary will be set to true if the failure might be due to a
@@ -14770,12 +14728,44 @@ class Sema final : public SemaBase {
   /// \returns true if an error occurred and satisfaction could not be checked,
   /// false otherwise.
   bool CheckConstraintSatisfaction(
-      ConstrainedDeclOrNestedRequirement Entity,
+      const NamedDecl *Template,
       ArrayRef<AssociatedConstraint> AssociatedConstraints,
       const MultiLevelTemplateArgumentList &TemplateArgLists,
-      SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
-      const ConceptReference *TopLevelConceptId = nullptr,
-      Expr **ConvertedExpr = nullptr);
+      SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
+    llvm::SmallVector<Expr *, 4> Converted;
+    return CheckConstraintSatisfaction(Template, AssociatedConstraints,
+                                       Converted, TemplateArgLists,
+                                       TemplateIDRange, Satisfaction);
+  }
+
+  /// \brief Check whether the given list of constraint expressions are
+  /// satisfied (as if in a 'conjunction') given template arguments.
+  /// Additionally, takes an empty list of Expressions which is populated with
+  /// the instantiated versions of the ConstraintExprs.
+  /// \param Template the template-like entity that triggered the constraints
+  /// check (either a concept or a constrained entity).
+  /// \param ConstraintExprs a list of constraint expressions, treated as if
+  /// they were 'AND'ed together.
+  /// \param ConvertedConstraints a out parameter that will get populated with
+  /// the instantiated version of the ConstraintExprs if we successfully checked
+  /// satisfaction.
+  /// \param TemplateArgList the multi-level list of template arguments to
+  /// substitute into the constraint expression. This should be relative to the
+  /// top-level (hence multi-level), since we need to instantiate fully at the
+  /// time of checking.
+  /// \param TemplateIDRange The source range of the template id that
+  /// caused the constraints check.
+  /// \param Satisfaction if true is returned, will contain details of the
+  /// satisfaction, with enough information to diagnose an unsatisfied
+  /// expression.
+  /// \returns true if an error occurred and satisfaction could not be checked,
+  /// false otherwise.
+  bool CheckConstraintSatisfaction(
+      const NamedDecl *Template,
+      ArrayRef<AssociatedConstraint> AssociatedConstraints,
+      llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
+      const MultiLevelTemplateArgumentList &TemplateArgList,
+      SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
 
   /// \brief Check whether the given non-dependent constraint expression is
   /// satisfied. Returns false and updates Satisfaction with the satisfaction
@@ -14841,17 +14831,16 @@ class Sema final : public SemaBase {
   /// \param First whether this is the first time an unsatisfied constraint is
   /// diagnosed for this error.
   void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction,
-                                     SourceLocation Loc = {},
                                      bool First = true);
 
   /// \brief Emit diagnostics explaining why a constraint expression was deemed
   /// unsatisfied.
   void
-  DiagnoseUnsatisfiedConstraint(const ConceptSpecializationExpr *ConstraintExpr,
+  DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
                                 bool First = true);
 
   const NormalizedConstraint *getNormalizedAssociatedConstraints(
-      ConstrainedDeclOrNestedRequirement Entity,
+      const NamedDecl *ConstrainedDecl,
       ArrayRef<AssociatedConstraint> AssociatedConstraints);
 
   /// \brief Check whether the given declaration's associated constraints are
@@ -14876,15 +14865,6 @@ class Sema final : public SemaBase {
       const NamedDecl *D1, ArrayRef<AssociatedConstraint> AC1,
       const NamedDecl *D2, ArrayRef<AssociatedConstraint> AC2);
 
-  /// Cache the satisfaction of an atomic constraint.
-  /// The key is based on the unsubstituted expression and the parameter
-  /// mapping. This lets us not substituting the mapping more than once,
-  /// which is (very!) expensive.
-  /// FIXME: this should be private.
-  llvm::DenseMap<llvm::FoldingSetNodeID,
-                 UnsubstitutedConstraintSatisfactionCacheResult>
-      UnsubstitutedConstraintSatisfactionCache;
-
 private:
   /// Caches pairs of template-like decls whose associated constraints were
   /// checked for subsumption and whether or not the first's constraints did in
@@ -14895,11 +14875,8 @@ class Sema final : public SemaBase {
   /// constrained declarations). If an error occurred while normalizing the
   /// associated constraints of the template or concept, nullptr will be cached
   /// here.
-  llvm::DenseMap<ConstrainedDeclOrNestedRequirement, NormalizedConstraint *>
-      NormalizationCache;
+  llvm::DenseMap<const NamedDecl *, NormalizedConstraint *> NormalizationCache;
 
-  /// Cache whether the associated constraint of a declaration
-  /// is satisfied.
   llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
       SatisfactionCache;
 
diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h
index 51ca1e16331f5..648a9c51ae6c1 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -16,406 +16,130 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
-#include "clang/AST/ExprConcepts.h"
 #include "clang/Basic/SourceLocation.h"
-#include "clang/Sema/Ownership.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
-#include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallVector.h"
 #include <optional>
 #include <utility>
 
 namespace clang {
 class Sema;
-class MultiLevelTemplateArgumentList;
 
-/// \brief A normalized constraint, as defined in C++ [temp.constr.normal], is
-/// either an atomic constraint, a conjunction of normalized constraints or a
-/// disjunction of normalized constraints.
-struct NormalizedConstraint {
-
-  enum class ConstraintKind : unsigned char {
-    Atomic = 0,
-    ConceptId,
-    FoldExpanded,
-    Compound,
-  };
-
-  enum CompoundConstraintKind : unsigned char {
-    CCK_Conjunction,
-    CCK_Disjunction
-  };
-  enum class FoldOperatorKind : unsigned char { And, Or };
-
-  using OccurenceList = llvm::SmallBitVector;
-
-protected:
-  using ExprOrConcept =
-      llvm::PointerUnion<const Expr *, const ConceptReference *>;
-
-  struct AtomicConstraintBits {
-    // Kind is the first member of all union members,
-    // as we rely on their initial common sequence.
-    LLVM_PREFERRED_TYPE(ConstraintKind)
-    unsigned Kind : 5;
-    unsigned Placeholder : 1;
-    unsigned PackSubstitutionIndex : 26;
-    // Indexes, IndexesForSubsumption, and Args are part of the common initial
-    // sequences of constraints that do have a mapping.
-
-    // Indexes of the parameters used in a constraint expression.
-    OccurenceList Indexes;
-    // Indexes of the parameters named directly in a constraint expression.
-    // FIXME: we should try to reduce the size of this struct?
-    OccurenceList IndexesForSubsumption;
-
-    TemplateArgumentLoc *Args;
-    TemplateParameterList *ParamList;
-    ExprOrConcept ConstraintExpr;
-    const NamedDecl *ConstraintDecl;
-  };
-
-  struct FoldExpandedConstraintBits {
-    LLVM_PREFERRED_TYPE(ConstraintKind)
-    unsigned Kind : 5;
-    LLVM_PREFERRED_TYPE(FoldOperatorKind)
-    unsigned FoldOperator : 1;
-    unsigned Placeholder : 26;
-    Occu...
[truncated]

Copy link

github-actions bot commented Oct 2, 2025

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff origin/main HEAD --extensions cpp,h -- clang/include/clang/AST/ASTConcept.h clang/include/clang/AST/ASTContext.h clang/include/clang/Sema/Sema.h clang/include/clang/Sema/SemaConcept.h clang/include/clang/Sema/Template.h clang/lib/AST/ASTConcept.cpp clang/lib/AST/ASTImporter.cpp clang/lib/Sema/SemaConcept.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Sema/SemaOverload.cpp clang/lib/Sema/SemaTemplate.cpp clang/lib/Sema/SemaTemplateDeduction.cpp clang/lib/Sema/SemaTemplateInstantiate.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReaderDecl.cpp clang/lib/Serialization/ASTReaderStmt.cpp clang/lib/Serialization/ASTWriterStmt.cpp clang/test/AST/ast-dump-concepts.cpp clang/test/AST/ast-dump-ctad-alias.cpp clang/test/CXX/drs/cwg25xx.cpp clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp clang/test/CXX/temp/temp.param/p10-2a.cpp clang/test/SemaCXX/cxx23-assume.cpp clang/test/SemaCXX/cxx2b-deducing-this.cpp clang/test/SemaCXX/cxx2c-fold-exprs.cpp clang/test/SemaCXX/cxx2c-template-template-param.cpp clang/test/SemaCXX/invalid-requirement-requires-expr.cpp clang/test/SemaCXX/overload-resolution-deferred-templates.cpp clang/test/SemaCXX/type-traits.cpp clang/test/SemaTemplate/concepts-recovery-expr.cpp clang/test/SemaTemplate/concepts-recursive-inst.cpp clang/test/SemaTemplate/concepts.cpp clang/test/SemaTemplate/deduction-guide.cpp clang/test/SemaTemplate/instantiate-abbreviated-template.cpp clang/test/SemaTemplate/instantiate-expanded-type-constraint.cpp clang/test/SemaTemplate/instantiate-requires-expr.cpp clang/test/SemaTemplate/instantiate-template-argument.cpp clang/test/SemaTemplate/pr52970.cpp libcxx/test/libcxx/algorithms/cpp17_iterator_concepts.verify.cpp

⚠️
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing origin/main to the base branch/commit you want to compare against.
⚠️

View the diff from clang-format here.
diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h
index 648a9c51a..df1d5a95d 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -77,15 +77,15 @@ struct NormalizedConstraint {
                      CompoundConstraint>
       Constraint;
 
-  NormalizedConstraint(AtomicConstraint *C): Constraint{C} { };
+  NormalizedConstraint(AtomicConstraint *C) : Constraint{C} {};
   NormalizedConstraint(FoldExpandedConstraint *C) : Constraint{C} {};
 
   NormalizedConstraint(ASTContext &C, NormalizedConstraint LHS,
                        NormalizedConstraint RHS, CompoundConstraintKind Kind);
 
   NormalizedConstraint(ASTContext &C, const NormalizedConstraint &Other);
-  NormalizedConstraint(NormalizedConstraint &&Other):
-      Constraint(Other.Constraint) {
+  NormalizedConstraint(NormalizedConstraint &&Other)
+      : Constraint(Other.Constraint) {
     Other.Constraint = nullptr;
   }
   NormalizedConstraint &operator=(const NormalizedConstraint &Other) = delete;
@@ -240,6 +240,6 @@ private:
   uint16_t getNewLiteralId();
 };
 
-} // clang
+} // namespace clang
 
 #endif // LLVM_CLANG_SEMA_SEMACONCEPT_H
diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp
index d658890e0..c4e88223c 100644
--- a/clang/lib/AST/ASTConcept.cpp
+++ b/clang/lib/AST/ASTConcept.cpp
@@ -74,9 +74,10 @@ ASTConstraintSatisfaction *ASTConstraintSatisfaction::Rebuild(
   return new (Mem) ASTConstraintSatisfaction(C, Satisfaction);
 }
 
-void ConstraintSatisfaction::Profile(
-    llvm::FoldingSetNodeID &ID, const ASTContext &C,
-    const NamedDecl *ConstraintOwner, ArrayRef<TemplateArgument> TemplateArgs) {
+void ConstraintSatisfaction::Profile(llvm::FoldingSetNodeID &ID,
+                                     const ASTContext &C,
+                                     const NamedDecl *ConstraintOwner,
+                                     ArrayRef<TemplateArgument> TemplateArgs) {
   ID.AddPointer(ConstraintOwner);
   ID.AddInteger(TemplateArgs.size());
   for (auto &Arg : TemplateArgs)
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index dc6d232d9..db2e596c1 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -85,7 +85,7 @@ public:
                                   OK_Ordinary, Loc, FPOptionsOverride{});
   }
 };
-}
+} // namespace
 
 bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
                                      Token NextToken, bool *PossibleNonPrimary,
@@ -146,14 +146,14 @@ bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
 
   if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
     Diag(ConstraintExpression->getExprLoc(),
-         diag::err_non_bool_atomic_constraint) << Type
-        << ConstraintExpression->getSourceRange();
+         diag::err_non_bool_atomic_constraint)
+        << Type << ConstraintExpression->getSourceRange();
     CheckForNonPrimary();
     return false;
   }
 
   if (PossibleNonPrimary)
-      *PossibleNonPrimary = false;
+    *PossibleNonPrimary = false;
   return true;
 }
 
@@ -164,14 +164,14 @@ struct SatisfactionStackRAII {
   SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
                         const llvm::FoldingSetNodeID &FSNID)
       : SemaRef(SemaRef) {
-      if (ND) {
+    if (ND) {
       SemaRef.PushSatisfactionStackEntry(ND, FSNID);
       Inserted = true;
-      }
+    }
   }
   ~SatisfactionStackRAII() {
-        if (Inserted)
-          SemaRef.PopSatisfactionStackEntry();
+    if (Inserted)
+      SemaRef.PopSatisfactionStackEntry();
   }
 };
 } // namespace
@@ -582,7 +582,8 @@ static bool CheckConstraintSatisfaction(
       TemplateArgsLists.getNumSubstitutedLevels() > 0
           ? TemplateArgsLists.getOutermost()
           : ArrayRef<TemplateArgument>{};
-  Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
+  Sema::InstantiatingTemplate Inst(
+      S, TemplateIDRange.getBegin(),
       Sema::InstantiatingTemplate::ConstraintsCheck{},
       const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
   if (Inst.isInvalid())
@@ -854,7 +855,6 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
       Satisfaction);
 }
 
-
 // Figure out the to-translation-unit depth for this function declaration for
 // the purpose of seeing if they differ by constraints. This isn't the same as
 // getTemplateDepth, because it includes already instantiated parents.
@@ -871,9 +871,10 @@ CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
 }
 
 namespace {
-  class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
+class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
   unsigned TemplateDepth = 0;
-  public:
+
+public:
   using inherited = TreeTransform<AdjustConstraintDepth>;
   AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
       : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
@@ -895,7 +896,7 @@ namespace {
     NewTL.setNameLoc(TL.getNameLoc());
     return Result;
   }
-  };
+};
 } // namespace
 
 static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
@@ -1161,73 +1162,74 @@ bool Sema::CheckFunctionTemplateConstraints(
 static void diagnoseUnsatisfiedRequirement(Sema &S,
                                            concepts::ExprRequirement *Req,
                                            bool First) {
-  assert(!Req->isSatisfied()
-         && "Diagnose() can only be used on an unsatisfied requirement");
+  assert(!Req->isSatisfied() &&
+         "Diagnose() can only be used on an unsatisfied requirement");
   switch (Req->getSatisfactionStatus()) {
-    case concepts::ExprRequirement::SS_Dependent:
-      llvm_unreachable("Diagnosing a dependent requirement");
-      break;
-    case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
-      auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
-      if (!SubstDiag->DiagMessage.empty())
-        S.Diag(SubstDiag->DiagLoc,
-               diag::note_expr_requirement_expr_substitution_error)
-               << (int)First << SubstDiag->SubstitutedEntity
-               << SubstDiag->DiagMessage;
-      else
-        S.Diag(SubstDiag->DiagLoc,
-               diag::note_expr_requirement_expr_unknown_substitution_error)
-            << (int)First << SubstDiag->SubstitutedEntity;
-      break;
-    }
-    case concepts::ExprRequirement::SS_NoexceptNotMet:
-      S.Diag(Req->getNoexceptLoc(),
-             diag::note_expr_requirement_noexcept_not_met)
-          << (int)First << Req->getExpr();
-      break;
-    case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
-      auto *SubstDiag =
-          Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
-      if (!SubstDiag->DiagMessage.empty())
-        S.Diag(SubstDiag->DiagLoc,
-               diag::note_expr_requirement_type_requirement_substitution_error)
-            << (int)First << SubstDiag->SubstitutedEntity
-            << SubstDiag->DiagMessage;
-      else
-        S.Diag(SubstDiag->DiagLoc,
-               diag::note_expr_requirement_type_requirement_unknown_substitution_error)
-            << (int)First << SubstDiag->SubstitutedEntity;
-      break;
-    }
-    case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
-      ConceptSpecializationExpr *ConstraintExpr =
-          Req->getReturnTypeRequirementSubstitutedConstraintExpr();
-      if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
-        // A simple case - expr type is the type being constrained and the concept
-        // was not provided arguments.
-        Expr *e = Req->getExpr();
-        S.Diag(e->getBeginLoc(),
-               diag::note_expr_requirement_constraints_not_satisfied_simple)
-            << (int)First << S.Context.getReferenceQualifiedType(e)
-            << ConstraintExpr->getNamedConcept();
-      } else {
-        S.Diag(ConstraintExpr->getBeginLoc(),
-               diag::note_expr_requirement_constraints_not_satisfied)
-            << (int)First << ConstraintExpr;
-      }
-      S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
-      break;
+  case concepts::ExprRequirement::SS_Dependent:
+    llvm_unreachable("Diagnosing a dependent requirement");
+    break;
+  case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
+    auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
+    if (!SubstDiag->DiagMessage.empty())
+      S.Diag(SubstDiag->DiagLoc,
+             diag::note_expr_requirement_expr_substitution_error)
+          << (int)First << SubstDiag->SubstitutedEntity
+          << SubstDiag->DiagMessage;
+    else
+      S.Diag(SubstDiag->DiagLoc,
+             diag::note_expr_requirement_expr_unknown_substitution_error)
+          << (int)First << SubstDiag->SubstitutedEntity;
+    break;
+  }
+  case concepts::ExprRequirement::SS_NoexceptNotMet:
+    S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)
+        << (int)First << Req->getExpr();
+    break;
+  case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
+    auto *SubstDiag =
+        Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
+    if (!SubstDiag->DiagMessage.empty())
+      S.Diag(SubstDiag->DiagLoc,
+             diag::note_expr_requirement_type_requirement_substitution_error)
+          << (int)First << SubstDiag->SubstitutedEntity
+          << SubstDiag->DiagMessage;
+    else
+      S.Diag(
+          SubstDiag->DiagLoc,
+          diag::
+              note_expr_requirement_type_requirement_unknown_substitution_error)
+          << (int)First << SubstDiag->SubstitutedEntity;
+    break;
+  }
+  case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
+    ConceptSpecializationExpr *ConstraintExpr =
+        Req->getReturnTypeRequirementSubstitutedConstraintExpr();
+    if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
+      // A simple case - expr type is the type being constrained and the concept
+      // was not provided arguments.
+      Expr *e = Req->getExpr();
+      S.Diag(e->getBeginLoc(),
+             diag::note_expr_requirement_constraints_not_satisfied_simple)
+          << (int)First << S.Context.getReferenceQualifiedType(e)
+          << ConstraintExpr->getNamedConcept();
+    } else {
+      S.Diag(ConstraintExpr->getBeginLoc(),
+             diag::note_expr_requirement_constraints_not_satisfied)
+          << (int)First << ConstraintExpr;
     }
-    case concepts::ExprRequirement::SS_Satisfied:
-      llvm_unreachable("We checked this above");
+    S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
+    break;
+  }
+  case concepts::ExprRequirement::SS_Satisfied:
+    llvm_unreachable("We checked this above");
   }
 }
 
 static void diagnoseUnsatisfiedRequirement(Sema &S,
                                            concepts::TypeRequirement *Req,
                                            bool First) {
-  assert(!Req->isSatisfied()
-         && "Diagnose() can only be used on an unsatisfied requirement");
+  assert(!Req->isSatisfied() &&
+         "Diagnose() can only be used on an unsatisfied requirement");
   switch (Req->getSatisfactionStatus()) {
   case concepts::TypeRequirement::SS_Dependent:
     llvm_unreachable("Diagnosing a dependent requirement");
@@ -1235,9 +1237,9 @@ static void diagnoseUnsatisfiedRequirement(Sema &S,
   case concepts::TypeRequirement::SS_SubstitutionFailure: {
     auto *SubstDiag = Req->getSubstitutionDiagnostic();
     if (!SubstDiag->DiagMessage.empty())
-      S.Diag(SubstDiag->DiagLoc,
-             diag::note_type_requirement_substitution_error) << (int)First
-          << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
+      S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
+          << (int)First << SubstDiag->SubstitutedEntity
+          << SubstDiag->DiagMessage;
     else
       S.Diag(SubstDiag->DiagLoc,
              diag::note_type_requirement_unknown_substitution_error)
@@ -1319,7 +1321,7 @@ static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
         BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
                                     Expr::SE_NoSideEffects,
                                     /*InConstantContext=*/true);
-        if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
+        if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {
           S.Diag(SubstExpr->getBeginLoc(),
                  diag::note_atomic_constraint_evaluated_to_false_elaborated)
               << (int)First << SubstExpr
@@ -1339,7 +1341,7 @@ static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
       S.Diag(
           CSE->getSourceRange().getBegin(),
           diag::
-          note_single_arg_concept_specialization_constraint_evaluated_to_false)
+              note_single_arg_concept_specialization_constraint_evaluated_to_false)
           << (int)First
           << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
           << CSE->getNamedConcept();
@@ -1392,9 +1394,8 @@ static void diagnoseUnsatisfiedConstraintExpr(
   diagnoseWellFormedUnsatisfiedConstraintExpr(S, cast<Expr *>(Record), First);
 }
 
-void
-Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
-                                    bool First) {
+void Sema::DiagnoseUnsatisfiedConstraint(
+    const ConstraintSatisfaction &Satisfaction, bool First) {
   assert(!Satisfaction.IsSatisfied &&
          "Attempted to diagnose a satisfied constraint");
   for (auto &Record : Satisfaction.Details) {
@@ -1404,8 +1405,7 @@ Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
 }
 
 void Sema::DiagnoseUnsatisfiedConstraint(
-    const ASTConstraintSatisfaction &Satisfaction,
-    bool First) {
+    const ASTConstraintSatisfaction &Satisfaction, bool First) {
   assert(!Satisfaction.IsSatisfied &&
          "Attempted to diagnose a satisfied constraint");
   for (auto &Record : Satisfaction) {
@@ -1430,8 +1430,8 @@ const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints(
         NormalizationCache
             .try_emplace(ConstrainedDecl,
                          Normalized
-                             ? new (Context) NormalizedConstraint(
-                                 std::move(*Normalized))
+                             ? new (Context)
+                                   NormalizedConstraint(std::move(*Normalized))
                              : nullptr)
             .first;
   }
@@ -1492,7 +1492,7 @@ substituteParameterMappings(Sema &S, NormalizedConstraint &N,
                 ArgsAsWritten->NumTemplateArgs > I
                     ? ArgsAsWritten->arguments()[I].getLocation()
                     : SourceLocation()));
-    Atomic.ParameterMapping.emplace(TempArgs,  OccurringIndices.count());
+    Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count());
   }
   SourceLocation InstLocBegin =
       ArgsAsWritten->arguments().empty()
@@ -1538,7 +1538,7 @@ NormalizedConstraint::NormalizedConstraint(ASTContext &C,
                                            NormalizedConstraint RHS,
                                            CompoundConstraintKind Kind)
     : Constraint{CompoundConstraint{
-          new(C) NormalizedConstraintPair{std::move(LHS), std::move(RHS)},
+          new (C) NormalizedConstraintPair{std::move(LHS), std::move(RHS)},
           Kind}} {}
 
 NormalizedConstraint::NormalizedConstraint(ASTContext &C,
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 2bf1511c5..86af11749 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4850,13 +4850,10 @@ void Sema::diagnoseMissingTemplateArguments(const CXXScopeSpec &SS,
   diagnoseMissingTemplateArguments(Name, Loc);
 }
 
-ExprResult
-Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
-                             SourceLocation TemplateKWLoc,
-                             const DeclarationNameInfo &ConceptNameInfo,
-                             NamedDecl *FoundDecl,
-                             ConceptDecl *NamedConcept,
-                             const TemplateArgumentListInfo *TemplateArgs) {
+ExprResult Sema::CheckConceptTemplateId(
+    const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+    const DeclarationNameInfo &ConceptNameInfo, NamedDecl *FoundDecl,
+    ConceptDecl *NamedConcept, const TemplateArgumentListInfo *TemplateArgs) {
   assert(NamedConcept && "A concept template id without a template?");
 
   if (NamedConcept->isInvalidDecl())
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index f6ee7452c..421fcf5d6 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -6677,9 +6677,8 @@ struct MarkUsedTemplateParameterVisitor : DynamicRecursiveASTVisitor {
   llvm::SmallBitVector &Used;
   unsigned Depth;
 
-  MarkUsedTemplateParameterVisitor(llvm::SmallBitVector &Used,
-                                   unsigned Depth)
-      : Used(Used), Depth(Depth) { }
+  MarkUsedTemplateParameterVisitor(llvm::SmallBitVector &Used, unsigned Depth)
+      : Used(Used), Depth(Depth) {}
 
   bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override {
     if (T->getDepth() == Depth)
@@ -7044,9 +7043,9 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
 
   case Type::UnaryTransform:
     if (!OnlyDeduced)
-      MarkUsedTemplateParameters(Ctx,
-                                 cast<UnaryTransformType>(T)->getUnderlyingType(),
-                                 OnlyDeduced, Depth, Used);
+      MarkUsedTemplateParameters(
+          Ctx, cast<UnaryTransformType>(T)->getUnderlyingType(), OnlyDeduced,
+          Depth, Used);
     break;
 
   case Type::PackExpansion:
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index f1c9c5c86..b68a6d123 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1375,543 +1375,541 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
 // Template Instantiation for Types
 //===----------------------------------------------------------------------===/
 namespace {
-  class TemplateInstantiator : public TreeTransform<TemplateInstantiator> {
-    const MultiLevelTemplateArgumentList &TemplateArgs;
-    SourceLocation Loc;
-    DeclarationName Entity;
-    // Whether to evaluate the C++20 constraints or simply substitute into them.
-    bool EvaluateConstraints = true;
-    // Whether Substitution was Incomplete, that is, we tried to substitute in
-    // any user provided template arguments which were null.
-    bool IsIncomplete = false;
-    // Whether an incomplete substituion should be treated as an error.
-    bool BailOutOnIncomplete;
-
-  private:
-    // CWG2770: Function parameters should be instantiated when they are
-    // needed by a satisfaction check of an atomic constraint or
-    // (recursively) by another function parameter.
-    bool maybeInstantiateFunctionParameterToScope(ParmVarDecl *OldParm);
-
-  public:
-    typedef TreeTransform<TemplateInstantiator> inherited;
-
-    TemplateInstantiator(Sema &SemaRef,
-                         const MultiLevelTemplateArgumentList &TemplateArgs,
-                         SourceLocation Loc, DeclarationName Entity,
-                         bool BailOutOnIncomplete = false)
-        : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
-          Entity(Entity), BailOutOnIncomplete(BailOutOnIncomplete) {}
-
-    void setEvaluateConstraints(bool B) {
-      EvaluateConstraints = B;
-    }
-    bool getEvaluateConstraints() {
-      return EvaluateConstraints;
-    }
-
-    /// Determine whether the given type \p T has already been
-    /// transformed.
-    ///
-    /// For the purposes of template instantiation, a type has already been
-    /// transformed if it is NULL or if it is not dependent.
-    bool AlreadyTransformed(QualType T);
+class TemplateInstantiator : public TreeTransform<TemplateInstantiator> {
+  const MultiLevelTemplateArgumentList &TemplateArgs;
+  SourceLocation Loc;
+  DeclarationName Entity;
+  // Whether to evaluate the C++20 constraints or simply substitute into them.
+  bool EvaluateConstraints = true;
+  // Whether Substitution was Incomplete, that is, we tried to substitute in
+  // any user provided template arguments which were null.
+  bool IsIncomplete = false;
+  // Whether an incomplete substituion should be treated as an error.
+  bool BailOutOnIncomplete;
+
+private:
+  // CWG2770: Function parameters should be instantiated when they are
+  // needed by a satisfaction check of an atomic constraint or
+  // (recursively) by another function parameter.
+  bool maybeInstantiateFunctionParameterToScope(ParmVarDecl *OldParm);
+
+public:
+  typedef TreeTransform<TemplateInstantiator> inherited;
+
+  TemplateInstantiator(Sema &SemaRef,
+                       const MultiLevelTemplateArgumentList &TemplateArgs,
+                       SourceLocation Loc, DeclarationName Entity,
+                       bool BailOutOnIncomplete = false)
+      : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
+        Entity(Entity), BailOutOnIncomplete(BailOutOnIncomplete) {}
+
+  void setEvaluateConstraints(bool B) { EvaluateConstraints = B; }
+  bool getEvaluateConstraints() { return EvaluateConstraints; }
+
+  /// Determine whether the given type \p T has already been
+  /// transformed.
+  ///
+  /// For the purposes of template instantiation, a type has already been
+  /// transformed if it is NULL or if it is not dependent.
+  bool AlreadyTransformed(QualType T);
+
+  /// Returns the location of the entity being instantiated, if known.
+  SourceLocation getBaseLocation() { return Loc; }
+
+  /// Returns the name of the entity being instantiated, if any.
+  DeclarationName getBaseEntity() { return Entity; }
+
+  /// Returns whether any substitution so far was incomplete.
+  bool getIsIncomplete() const { return IsIncomplete; }
+
+  /// Sets the "base" location and entity when that
+  /// information is known based on another transformation.
+  void setBase(SourceLocation Loc, DeclarationName Entity) {
+    this->Loc = Loc;
+    this->Entity = Entity;
+  }
 
-    /// Returns the location of the entity being instantiated, if known.
-    SourceLocation getBaseLocation() { return Loc; }
+  unsigned TransformTemplateDepth(unsigned Depth) {
+    return TemplateArgs.getNewDepth(Depth);
+  }
 
-    /// Returns the name of the entity being instantiated, if any.
-    DeclarationName getBaseEntity() { return Entity; }
+  bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
+                               SourceRange PatternRange,
+                               ArrayRef<UnexpandedParameterPack> Unexpanded,
+                               bool FailOnPackProducingTemplates,
+                               bool &ShouldExpand, bool &RetainExpansion,
+                               UnsignedOrNone &NumExpansions) {
+    if (SemaRef.CurrentInstantiationScope &&
+        SemaRef.inConstraintSubstitution()) {
+      for (UnexpandedParameterPack ParmPack : Unexpanded) {
+        NamedDecl *VD = ParmPack.first.dyn_cast<NamedDecl *>();
+        if (auto *PVD = dyn_cast_if_present<ParmVarDecl>(VD);
+            PVD && maybeInstantiateFunctionParameterToScope(PVD))
+          return true;
+      }
+    }
 
-    /// Returns whether any substitution so far was incomplete.
-    bool getIsIncomplete() const { return IsIncomplete; }
+    return getSema().CheckParameterPacksForExpansion(
+        EllipsisLoc, PatternRange, Unexpanded, TemplateArgs,
+        FailOnPackProducingTemplates, ShouldExpand, RetainExpansion,
+        NumExpansions);
+  }
 
-    /// Sets the "base" location and entity when that
-    /// information is known based on another transformation.
-    void setBase(SourceLocation Loc, DeclarationName Entity) {
-      this->Loc = Loc;
-      this->Entity = Entity;
-    }
+  void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
+    SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack);
+  }
 
-    unsigned TransformTemplateDepth(unsigned Depth) {
-      return TemplateArgs.getNewDepth(Depth);
+  TemplateArgument ForgetPartiallySubstitutedPack() {
+    TemplateArgument Result;
+    if (NamedDecl *PartialPack =
+            SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()) {
+      MultiLevelTemplateArgumentList &TemplateArgs =
+          const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+      unsigned Depth, Index;
+      std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+      if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
+        Result = TemplateArgs(Depth, Index);
+        TemplateArgs.setArgument(Depth, Index, TemplateArgument());
+      } else {
+        IsIncomplete = true;
+        if (BailOutOnIncomplete)
+          return TemplateArgument();
+      }
     }
 
-    bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
-                                 SourceRange PatternRange,
-                                 ArrayRef<UnexpandedParameterPack> Unexpanded,
-                                 bool FailOnPackProducingTemplates,
-                                 bool &ShouldExpand, bool &RetainExpansion,
-                                 UnsignedOrNone &NumExpansions) {
-      if (SemaRef.CurrentInstantiationScope &&
-          SemaRef.inConstraintSubstitution()) {
-        for (UnexpandedParameterPack ParmPack : Unexpanded) {
-          NamedDecl *VD = ParmPack.first.dyn_cast<NamedDecl *>();
-          if (auto *PVD = dyn_cast_if_present<ParmVarDecl>(VD);
-              PVD && maybeInstantiateFunctionParameterToScope(PVD))
-            return true;
-        }
-      }
+    return Result;
+  }
 
-      return getSema().CheckParameterPacksForExpansion(
-          EllipsisLoc, PatternRange, Unexpanded, TemplateArgs,
-          FailOnPackProducingTemplates, ShouldExpand, RetainExpansion,
-          NumExpansions);
-    }
+  void RememberPartiallySubstitutedPack(TemplateArgument Arg) {
+    if (Arg.isNull())
+      return;
 
-    void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
-      SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack);
+    if (NamedDecl *PartialPack =
+            SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()) {
+      MultiLevelTemplateArgumentList &TemplateArgs =
+          const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+      unsigned Depth, Index;
+      std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+      TemplateArgs.setArgument(Depth, Index, Arg);
     }
+  }
 
-    TemplateArgument ForgetPartiallySubstitutedPack() {
-      TemplateArgument Result;
-      if (NamedDecl *PartialPack
-            = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
-        MultiLevelTemplateArgumentList &TemplateArgs
-          = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
-        unsigned Depth, Index;
-        std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
-        if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
-          Result = TemplateArgs(Depth, Index);
-          TemplateArgs.setArgument(Depth, Index, TemplateArgument());
-        } else {
-          IsIncomplete = true;
-          if (BailOutOnIncomplete)
-            return TemplateArgument();
-        }
-      }
+  MultiLevelTemplateArgumentList ForgetSubstitution() {
+    MultiLevelTemplateArgumentList New;
+    New.addOuterRetainedLevels(this->TemplateArgs.getNumLevels());
 
-      return Result;
-    }
+    MultiLevelTemplateArgumentList Old =
+        const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+    const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs) =
+        std::move(New);
+    return Old;
+  }
+  void RememberSubstitution(MultiLevelTemplateArgumentList Old) {
+    const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs) =
+        std::move(Old);
+  }
 
-    void RememberPartiallySubstitutedPack(TemplateArgument Arg) {
-      if (Arg.isNull())
-        return;
-
-      if (NamedDecl *PartialPack
-            = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
-        MultiLevelTemplateArgumentList &TemplateArgs
-        = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
-        unsigned Depth, Index;
-        std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
-        TemplateArgs.setArgument(Depth, Index, Arg);
-      }
-    }
+  TemplateArgument
+  getTemplateArgumentPackPatternForRewrite(const TemplateArgument &TA) {
+    if (TA.getKind() != TemplateArgument::Pack)
+      return TA;
+    if (SemaRef.ArgPackSubstIndex)
+      return SemaRef.getPackSubstitutedTemplateArgument(TA);
+    assert(TA.pack_size() == 1 && TA.pack_begin()->isPackExpansion() &&
+           "unexpected pack arguments in template rewrite");
+    TemplateArgument Arg = *TA.pack_begin();
+    if (Arg.isPackExpansion())
+      Arg = Arg.getPackExpansionPattern();
+    return Arg;
+  }
 
-    MultiLevelTemplateArgumentList ForgetSubstitution() {
-      MultiLevelTemplateArgumentList New;
-      New.addOuterRetainedLevels(this->TemplateArgs.getNumLevels());
+  /// Transform the given declaration by instantiating a reference to
+  /// this declaration.
+  Decl *TransformDecl(SourceLocation Loc, Decl *D);
 
-      MultiLevelTemplateArgumentList Old =
-          const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
-      const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs) =
-          std::move(New);
-      return Old;
-    }
-    void RememberSubstitution(MultiLevelTemplateArgumentList Old) {
-      const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs) =
-          std::move(Old);
-    }
+  void transformAttrs(Decl *Old, Decl *New) {
+    SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
+  }
 
-    TemplateArgument
-    getTemplateArgumentPackPatternForRewrite(const TemplateArgument &TA) {
-      if (TA.getKind() != TemplateArgument::Pack)
-        return TA;
-      if (SemaRef.ArgPackSubstIndex)
-        return SemaRef.getPackSubstitutedTemplateArgument(TA);
-      assert(TA.pack_size() == 1 && TA.pack_begin()->isPackExpansion() &&
-             "unexpected pack arguments in template rewrite");
-      TemplateArgument Arg = *TA.pack_begin();
-      if (Arg.isPackExpansion())
-        Arg = Arg.getPackExpansionPattern();
-      return Arg;
+  void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> NewDecls) {
+    if (Old->isParameterPack() &&
+        (NewDecls.size() != 1 || !NewDecls.front()->isParameterPack())) {
+      SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
+      for (auto *New : NewDecls)
+        SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(
+            Old, cast<VarDecl>(New));
+      return;
     }
 
-    /// Transform the given declaration by instantiating a reference to
-    /// this declaration.
-    Decl *TransformDecl(SourceLocation Loc, Decl *D);
-
-    void transformAttrs(Decl *Old, Decl *New) {
-      SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
+    assert(NewDecls.size() == 1 &&
+           "should only have multiple expansions for a pack");
+    Decl *New = NewDecls.front();
+
+    // If we've instantiated the call operator of a lambda or the call
+    // operator template of a generic lambda, update the "instantiation of"
+    // information.
+    auto *NewMD = dyn_cast<CXXMethodDecl>(New);
+    if (NewMD && isLambdaCallOperator(NewMD)) {
+      auto *OldMD = dyn_cast<CXXMethodDecl>(Old);
+      if (auto *NewTD = NewMD->getDescribedFunctionTemplate())
+        NewTD->setInstantiatedFromMemberTemplate(
+            OldMD->getDescribedFunctionTemplate());
+      else
+        NewMD->setInstantiationOfMemberFunction(OldMD,
+                                                TSK_ImplicitInstantiation);
     }
 
-    void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> NewDecls) {
-      if (Old->isParameterPack() &&
-          (NewDecls.size() != 1 || !NewDecls.front()->isParameterPack())) {
-        SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
-        for (auto *New : NewDecls)
-          SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(
-              Old, cast<VarDecl>(New));
-        return;
-      }
+    SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);
 
-      assert(NewDecls.size() == 1 &&
-             "should only have multiple expansions for a pack");
-      Decl *New = NewDecls.front();
-
-      // If we've instantiated the call operator of a lambda or the call
-      // operator template of a generic lambda, update the "instantiation of"
-      // information.
-      auto *NewMD = dyn_cast<CXXMethodDecl>(New);
-      if (NewMD && isLambdaCallOperator(NewMD)) {
-        auto *OldMD = dyn_cast<CXXMethodDecl>(Old);
-        if (auto *NewTD = NewMD->getDescribedFunctionTemplate())
-          NewTD->setInstantiatedFromMemberTemplate(
-              OldMD->getDescribedFunctionTemplate());
-        else
-          NewMD->setInstantiationOfMemberFunction(OldMD,
-                                                  TSK_ImplicitInstantiation);
-      }
+    // We recreated a local declaration, but not by instantiating it. There
+    // may be pending dependent diagnostics to produce.
+    if (auto *DC = dyn_cast<DeclContext>(Old);
+        DC && DC->isDependentContext() && DC->isFunctionOrMethod())
+      SemaRef.PerformDependentDiagnostics(DC, TemplateArgs);
+  }
 
-      SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);
+  /// Transform the definition of the given declaration by
+  /// instantiating it.
+  Decl *TransformDefinition(SourceLocation Loc, Decl *D);
 
-      // We recreated a local declaration, but not by instantiating it. There
-      // may be pending dependent diagnostics to produce.
-      if (auto *DC = dyn_cast<DeclContext>(Old);
-          DC && DC->isDependentContext() && DC->isFunctionOrMethod())
-        SemaRef.PerformDependentDiagnostics(DC, TemplateArgs);
-    }
+  /// Transform the first qualifier within a scope by instantiating the
+  /// declaration.
+  NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
 
-    /// Transform the definition of the given declaration by
-    /// instantiating it.
-    Decl *TransformDefinition(SourceLocation Loc, Decl *D);
-
-    /// Transform the first qualifier within a scope by instantiating the
-    /// declaration.
-    NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
-
-    bool TransformExceptionSpec(SourceLocation Loc,
-                                FunctionProtoType::ExceptionSpecInfo &ESI,
-                                SmallVectorImpl<QualType> &Exceptions,
-                                bool &Changed);
-
-    /// Rebuild the exception declaration and register the declaration
-    /// as an instantiated local.
-    VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
-                                  TypeSourceInfo *Declarator,
-                                  SourceLocation StartLoc,
-                                  SourceLocation NameLoc,
-                                  IdentifierInfo *Name);
-
-    /// Rebuild the Objective-C exception declaration and register the
-    /// declaration as an instantiated local.
-    VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
-                                      TypeSourceInfo *TSInfo, QualType T);
-
-    TemplateName
-    TransformTemplateName(NestedNameSpecifierLoc &QualifierLoc,
-                          SourceLocation TemplateKWLoc, TemplateName Name,
-                          SourceLocation NameLoc,
-                          QualType ObjectType = QualType(),
-                          NamedDecl *FirstQualifierInScope = nullptr,
-                          bool AllowInjectedClassName = false);
-
-    const AnnotateAttr *TransformAnnotateAttr(const AnnotateAttr *AA);
-    const CXXAssumeAttr *TransformCXXAssumeAttr(const CXXAssumeAttr *AA);
-    const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH);
-    const NoInlineAttr *TransformStmtNoInlineAttr(const Stmt *OrigS,
-                                                  const Stmt *InstS,
-                                                  const NoInlineAttr *A);
-    const AlwaysInlineAttr *
-    TransformStmtAlwaysInlineAttr(const Stmt *OrigS, const Stmt *InstS,
-                                  const AlwaysInlineAttr *A);
-    const CodeAlignAttr *TransformCodeAlignAttr(const CodeAlignAttr *CA);
-    const OpenACCRoutineDeclAttr *
-    TransformOpenACCRoutineDeclAttr(const OpenACCRoutineDeclAttr *A);
-    ExprResult TransformPredefinedExpr(PredefinedExpr *E);
-    ExprResult TransformDeclRefExpr(DeclRefExpr *E);
-    ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
-
-    ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
-                                            NonTypeTemplateParmDecl *D);
-
-    /// Rebuild a DeclRefExpr for a VarDecl reference.
-    ExprResult RebuildVarDeclRefExpr(ValueDecl *PD, SourceLocation Loc);
-
-    /// Transform a reference to a function or init-capture parameter pack.
-    ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E, ValueDecl *PD);
-
-    /// Transform a FunctionParmPackExpr which was built when we couldn't
-    /// expand a function parameter pack reference which refers to an expanded
-    /// pack.
-    ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
-
-    QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
-                                        FunctionProtoTypeLoc TL) {
-      // Call the base version; it will forward to our overridden version below.
-      return inherited::TransformFunctionProtoType(TLB, TL);
-    }
+  bool TransformExceptionSpec(SourceLocation Loc,
+                              FunctionProtoType::ExceptionSpecInfo &ESI,
+                              SmallVectorImpl<QualType> &Exceptions,
+                              bool &Changed);
+
+  /// Rebuild the exception declaration and register the declaration
+  /// as an instantiated local.
+  VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
+                                TypeSourceInfo *Declarator,
+                                SourceLocation StartLoc, SourceLocation NameLoc,
+                                IdentifierInfo *Name);
+
+  /// Rebuild the Objective-C exception declaration and register the
+  /// declaration as an instantiated local.
+  VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
+                                    TypeSourceInfo *TSInfo, QualType T);
+
+  TemplateName TransformTemplateName(NestedNameSpecifierLoc &QualifierLoc,
+                                     SourceLocation TemplateKWLoc,
+                                     TemplateName Name, SourceLocation NameLoc,
+                                     QualType ObjectType = QualType(),
+                                     NamedDecl *FirstQualifierInScope = nullptr,
+                                     bool AllowInjectedClassName = false);
+
+  const AnnotateAttr *TransformAnnotateAttr(const AnnotateAttr *AA);
+  const CXXAssumeAttr *TransformCXXAssumeAttr(const CXXAssumeAttr *AA);
+  const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH);
+  const NoInlineAttr *TransformStmtNoInlineAttr(const Stmt *OrigS,
+                                                const Stmt *InstS,
+                                                const NoInlineAttr *A);
+  const AlwaysInlineAttr *
+  TransformStmtAlwaysInlineAttr(const Stmt *OrigS, const Stmt *InstS,
+                                const AlwaysInlineAttr *A);
+  const CodeAlignAttr *TransformCodeAlignAttr(const CodeAlignAttr *CA);
+  const OpenACCRoutineDeclAttr *
+  TransformOpenACCRoutineDeclAttr(const OpenACCRoutineDeclAttr *A);
+  ExprResult TransformPredefinedExpr(PredefinedExpr *E);
+  ExprResult TransformDeclRefExpr(DeclRefExpr *E);
+  ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+
+  ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
+                                          NonTypeTemplateParmDecl *D);
+
+  /// Rebuild a DeclRefExpr for a VarDecl reference.
+  ExprResult RebuildVarDeclRefExpr(ValueDecl *PD, SourceLocation Loc);
+
+  /// Transform a reference to a function or init-capture parameter pack.
+  ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E, ValueDecl *PD);
+
+  /// Transform a FunctionParmPackExpr which was built when we couldn't
+  /// expand a function parameter pack reference which refers to an expanded
+  /// pack.
+  ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
+
+  QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                      FunctionProtoTypeLoc TL) {
+    // Call the base version; it will forward to our overridden version below.
+    return inherited::TransformFunctionProtoType(TLB, TL);
+  }
 
-    QualType TransformTagType(TypeLocBuilder &TLB, TagTypeLoc TL) {
-      auto Type = inherited::TransformTagType(TLB, TL);
-      if (!Type.isNull())
-        return Type;
-      // Special case for transforming a deduction guide, we return a
-      // transformed TemplateSpecializationType.
-      // FIXME: Why is this hack necessary?
-      if (const auto *ICNT = dyn_cast<InjectedClassNameType>(TL.getTypePtr());
-          ICNT && SemaRef.CodeSynthesisContexts.back().Kind ==
-                      Sema::CodeSynthesisContext::BuildingDeductionGuides) {
-        Type = inherited::TransformType(
-            ICNT->getOriginalDecl()->getCanonicalTemplateSpecializationType(
-                SemaRef.Context));
-        TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc());
-      }
+  QualType TransformTagType(TypeLocBuilder &TLB, TagTypeLoc TL) {
+    auto Type = inherited::TransformTagType(TLB, TL);
+    if (!Type.isNull())
       return Type;
+    // Special case for transforming a deduction guide, we return a
+    // transformed TemplateSpecializationType.
+    // FIXME: Why is this hack necessary?
+    if (const auto *ICNT = dyn_cast<InjectedClassNameType>(TL.getTypePtr());
+        ICNT && SemaRef.CodeSynthesisContexts.back().Kind ==
+                    Sema::CodeSynthesisContext::BuildingDeductionGuides) {
+      Type = inherited::TransformType(
+          ICNT->getOriginalDecl()->getCanonicalTemplateSpecializationType(
+              SemaRef.Context));
+      TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc());
     }
-    // Override the default version to handle a rewrite-template-arg-pack case
-    // for building a deduction guide.
-    bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
-                                   TemplateArgumentLoc &Output,
-                                   bool Uneval = false) {
-      const TemplateArgument &Arg = Input.getArgument();
-      std::vector<TemplateArgument> TArgs;
-      switch (Arg.getKind()) {
-      case TemplateArgument::Pack:
-        assert(SemaRef.CodeSynthesisContexts.empty() ||
-               SemaRef.CodeSynthesisContexts.back().Kind ==
-                   Sema::CodeSynthesisContext::BuildingDeductionGuides);
-        // Literally rewrite the template argument pack, instead of unpacking
-        // it.
-        for (auto &pack : Arg.getPackAsArray()) {
-          TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(
-              pack, QualType(), SourceLocation{});
-          TemplateArgumentLoc Output;
-          if (TransformTemplateArgument(Input, Output, Uneval))
-            return true; // fails
-          TArgs.push_back(Output.getArgument());
-        }
-        Output = SemaRef.getTrivialTemplateArgumentLoc(
-            TemplateArgument(llvm::ArrayRef(TArgs).copy(SemaRef.Context)),
-            QualType(), SourceLocation{});
-        return false;
-      default:
-        break;
+    return Type;
+  }
+  // Override the default version to handle a rewrite-template-arg-pack case
+  // for building a deduction guide.
+  bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
+                                 TemplateArgumentLoc &Output,
+                                 bool Uneval = false) {
+    const TemplateArgument &Arg = Input.getArgument();
+    std::vector<TemplateArgument> TArgs;
+    switch (Arg.getKind()) {
+    case TemplateArgument::Pack:
+      assert(SemaRef.CodeSynthesisContexts.empty() ||
+             SemaRef.CodeSynthesisContexts.back().Kind ==
+                 Sema::CodeSynthesisContext::BuildingDeductionGuides);
+      // Literally rewrite the template argument pack, instead of unpacking
+      // it.
+      for (auto &pack : Arg.getPackAsArray()) {
+        TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(
+            pack, QualType(), SourceLocation{});
+        TemplateArgumentLoc Output;
+        if (TransformTemplateArgument(Input, Output, Uneval))
+          return true; // fails
+        TArgs.push_back(Output.getArgument());
       }
-      return inherited::TransformTemplateArgument(Input, Output, Uneval);
+      Output = SemaRef.getTrivialTemplateArgumentLoc(
+          TemplateArgument(llvm::ArrayRef(TArgs).copy(SemaRef.Context)),
+          QualType(), SourceLocation{});
+      return false;
+    default:
+      break;
     }
+    return inherited::TransformTemplateArgument(Input, Output, Uneval);
+  }
 
-    using TreeTransform::TransformTemplateSpecializationType;
-    QualType
-    TransformTemplateSpecializationType(TypeLocBuilder &TLB,
-                                        TemplateSpecializationTypeLoc TL) {
-      auto *T = TL.getTypePtr();
-      if (!getSema().ArgPackSubstIndex || !T->isSugared() ||
-          !isPackProducingBuiltinTemplateName(T->getTemplateName()))
-        return TreeTransform::TransformTemplateSpecializationType(TLB, TL);
-      // Look through sugar to get to the SubstBuiltinTemplatePackType that we
-      // need to substitute into.
-
-      // `TransformType` code below will handle picking the element from a pack
-      // with the index `ArgPackSubstIndex`.
-      // FIXME: add ability to represent sugarred type for N-th element of a
-      // builtin pack and produce the sugar here.
-      QualType R = TransformType(T->desugar());
-      TLB.pushTrivial(getSema().getASTContext(), R, TL.getBeginLoc());
-      return R;
-    }
+  using TreeTransform::TransformTemplateSpecializationType;
+  QualType
+  TransformTemplateSpecializationType(TypeLocBuilder &TLB,
+                                      TemplateSpecializationTypeLoc TL) {
+    auto *T = TL.getTypePtr();
+    if (!getSema().ArgPackSubstIndex || !T->isSugared() ||
+        !isPackProducingBuiltinTemplateName(T->getTemplateName()))
+      return TreeTransform::TransformTemplateSpecializationType(TLB, TL);
+    // Look through sugar to get to the SubstBuiltinTemplatePackType that we
+    // need to substitute into.
+
+    // `TransformType` code below will handle picking the element from a pack
+    // with the index `ArgPackSubstIndex`.
+    // FIXME: add ability to represent sugarred type for N-th element of a
+    // builtin pack and produce the sugar here.
+    QualType R = TransformType(T->desugar());
+    TLB.pushTrivial(getSema().getASTContext(), R, TL.getBeginLoc());
+    return R;
+  }
 
-    UnsignedOrNone ComputeSizeOfPackExprWithoutSubstitution(
-        ArrayRef<TemplateArgument> PackArgs) {
-      // Don't do this when rewriting template parameters for CTAD:
-      //   1) The heuristic needs the unpacked Subst* nodes to figure out the
-      //   expanded size, but this never applies since Subst* nodes are not
-      //   created in rewrite scenarios.
-      //
-      //   2) The heuristic substitutes into the pattern with pack expansion
-      //   suppressed, which does not meet the requirements for argument
-      //   rewriting when template arguments include a non-pack matching against
-      //   a pack, particularly when rewriting an alias CTAD.
-      if (TemplateArgs.isRewrite())
-        return std::nullopt;
-
-      return inherited::ComputeSizeOfPackExprWithoutSubstitution(PackArgs);
-    }
+  UnsignedOrNone ComputeSizeOfPackExprWithoutSubstitution(
+      ArrayRef<TemplateArgument> PackArgs) {
+    // Don't do this when rewriting template parameters for CTAD:
+    //   1) The heuristic needs the unpacked Subst* nodes to figure out the
+    //   expanded size, but this never applies since Subst* nodes are not
+    //   created in rewrite scenarios.
+    //
+    //   2) The heuristic substitutes into the pattern with pack expansion
+    //   suppressed, which does not meet the requirements for argument
+    //   rewriting when template arguments include a non-pack matching against
+    //   a pack, particularly when rewriting an alias CTAD.
+    if (TemplateArgs.isRewrite())
+      return std::nullopt;
 
-    template<typename Fn>
-    QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
-                                        FunctionProtoTypeLoc TL,
-                                        CXXRecordDecl *ThisContext,
-                                        Qualifiers ThisTypeQuals,
-                                        Fn TransformExceptionSpec);
-
-    ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
-                                            int indexAdjustment,
-                                            UnsignedOrNone NumExpansions,
-                                            bool ExpectParameterPack);
-
-    using inherited::TransformTemplateTypeParmType;
-    /// Transforms a template type parameter type by performing
-    /// substitution of the corresponding template type argument.
-    QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
-                                           TemplateTypeParmTypeLoc TL,
-                                           bool SuppressObjCLifetime);
-
-    QualType BuildSubstTemplateTypeParmType(
-        TypeLocBuilder &TLB, bool SuppressObjCLifetime, bool Final,
-        Decl *AssociatedDecl, unsigned Index, UnsignedOrNone PackIndex,
-        TemplateArgument Arg, SourceLocation NameLoc);
-
-    /// Transforms an already-substituted template type parameter pack
-    /// into either itself (if we aren't substituting into its pack expansion)
-    /// or the appropriate substituted argument.
-    using inherited::TransformSubstTemplateTypeParmPackType;
-    QualType
-    TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
-                                           SubstTemplateTypeParmPackTypeLoc TL,
-                                           bool SuppressObjCLifetime);
-    QualType
-    TransformSubstBuiltinTemplatePackType(TypeLocBuilder &TLB,
-                                          SubstBuiltinTemplatePackTypeLoc TL);
-
-    CXXRecordDecl::LambdaDependencyKind
-    ComputeLambdaDependency(LambdaScopeInfo *LSI) {
-      if (auto TypeAlias =
-              TemplateInstArgsHelpers::getEnclosingTypeAliasTemplateDecl(
-                  getSema());
-          TypeAlias && TemplateInstArgsHelpers::isLambdaEnclosedByTypeAliasDecl(
-                           LSI->CallOperator, TypeAlias.PrimaryTypeAliasDecl)) {
-        unsigned TypeAliasDeclDepth = TypeAlias.Template->getTemplateDepth();
-        if (TypeAliasDeclDepth >= TemplateArgs.getNumSubstitutedLevels())
+    return inherited::ComputeSizeOfPackExprWithoutSubstitution(PackArgs);
+  }
+
+  template <typename Fn>
+  QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                      FunctionProtoTypeLoc TL,
+                                      CXXRecordDecl *ThisContext,
+                                      Qualifiers ThisTypeQuals,
+                                      Fn TransformExceptionSpec);
+
+  ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                          int indexAdjustment,
+                                          UnsignedOrNone NumExpansions,
+                                          bool ExpectParameterPack);
+
+  using inherited::TransformTemplateTypeParmType;
+  /// Transforms a template type parameter type by performing
+  /// substitution of the corresponding template type argument.
+  QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+                                         TemplateTypeParmTypeLoc TL,
+                                         bool SuppressObjCLifetime);
+
+  QualType BuildSubstTemplateTypeParmType(TypeLocBuilder &TLB,
+                                          bool SuppressObjCLifetime, bool Final,
+                                          Decl *AssociatedDecl, unsigned Index,
+                                          UnsignedOrNone PackIndex,
+                                          TemplateArgument Arg,
+                                          SourceLocation NameLoc);
+
+  /// Transforms an already-substituted template type parameter pack
+  /// into either itself (if we aren't substituting into its pack expansion)
+  /// or the appropriate substituted argument.
+  using inherited::TransformSubstTemplateTypeParmPackType;
+  QualType
+  TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
+                                         SubstTemplateTypeParmPackTypeLoc TL,
+                                         bool SuppressObjCLifetime);
+  QualType
+  TransformSubstBuiltinTemplatePackType(TypeLocBuilder &TLB,
+                                        SubstBuiltinTemplatePackTypeLoc TL);
+
+  CXXRecordDecl::LambdaDependencyKind
+  ComputeLambdaDependency(LambdaScopeInfo *LSI) {
+    if (auto TypeAlias =
+            TemplateInstArgsHelpers::getEnclosingTypeAliasTemplateDecl(
+                getSema());
+        TypeAlias && TemplateInstArgsHelpers::isLambdaEnclosedByTypeAliasDecl(
+                         LSI->CallOperator, TypeAlias.PrimaryTypeAliasDecl)) {
+      unsigned TypeAliasDeclDepth = TypeAlias.Template->getTemplateDepth();
+      if (TypeAliasDeclDepth >= TemplateArgs.getNumSubstitutedLevels())
+        return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent;
+      for (const TemplateArgument &TA : TypeAlias.AssociatedTemplateArguments)
+        if (TA.isDependent())
           return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent;
-        for (const TemplateArgument &TA : TypeAlias.AssociatedTemplateArguments)
-          if (TA.isDependent())
-            return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent;
-      }
-      return inherited::ComputeLambdaDependency(LSI);
     }
+    return inherited::ComputeLambdaDependency(LSI);
+  }
 
-    ExprResult TransformLambdaExpr(LambdaExpr *E) {
-      // Do not rebuild lambdas to avoid creating a new type.
-      // Lambdas have already been processed inside their eval contexts.
-      if (SemaRef.RebuildingImmediateInvocation)
-        return E;
-      LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true,
-                                    /*InstantiatingLambdaOrBlock=*/true);
-      Sema::ConstraintEvalRAII<TemplateInstantiator> RAII(*this);
+  ExprResult TransformLambdaExpr(LambdaExpr *E) {
+    // Do not rebuild lambdas to avoid creating a new type.
+    // Lambdas have already been processed inside their eval contexts.
+    if (SemaRef.RebuildingImmediateInvocation)
+      return E;
+    LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true,
+                                  /*InstantiatingLambdaOrBlock=*/true);
+    Sema::ConstraintEvalRAII<TemplateInstantiator> RAII(*this);
 
-      return inherited::TransformLambdaExpr(E);
-    }
+    return inherited::TransformLambdaExpr(E);
+  }
 
-    ExprResult TransformBlockExpr(BlockExpr *E) {
-      LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true,
-                                    /*InstantiatingLambdaOrBlock=*/true);
-      return inherited::TransformBlockExpr(E);
-    }
+  ExprResult TransformBlockExpr(BlockExpr *E) {
+    LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true,
+                                  /*InstantiatingLambdaOrBlock=*/true);
+    return inherited::TransformBlockExpr(E);
+  }
 
-    ExprResult RebuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
-                                 LambdaScopeInfo *LSI) {
-      CXXMethodDecl *MD = LSI->CallOperator;
-      for (ParmVarDecl *PVD : MD->parameters()) {
-        assert(PVD && "null in a parameter list");
-        if (!PVD->hasDefaultArg())
-          continue;
-        Expr *UninstExpr = PVD->getUninstantiatedDefaultArg();
-        // FIXME: Obtain the source location for the '=' token.
-        SourceLocation EqualLoc = UninstExpr->getBeginLoc();
-        if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) {
-          // If substitution fails, the default argument is set to a
-          // RecoveryExpr that wraps the uninstantiated default argument so
-          // that downstream diagnostics are omitted.
-          ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
-              UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(), {UninstExpr},
-              UninstExpr->getType());
-          if (ErrorResult.isUsable())
-            PVD->setDefaultArg(ErrorResult.get());
-        }
+  ExprResult RebuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
+                               LambdaScopeInfo *LSI) {
+    CXXMethodDecl *MD = LSI->CallOperator;
+    for (ParmVarDecl *PVD : MD->parameters()) {
+      assert(PVD && "null in a parameter list");
+      if (!PVD->hasDefaultArg())
+        continue;
+      Expr *UninstExpr = PVD->getUninstantiatedDefaultArg();
+      // FIXME: Obtain the source location for the '=' token.
+      SourceLocation EqualLoc = UninstExpr->getBeginLoc();
+      if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) {
+        // If substitution fails, the default argument is set to a
+        // RecoveryExpr that wraps the uninstantiated default argument so
+        // that downstream diagnostics are omitted.
+        ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
+            UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(), {UninstExpr},
+            UninstExpr->getType());
+        if (ErrorResult.isUsable())
+          PVD->setDefaultArg(ErrorResult.get());
       }
-      return inherited::RebuildLambdaExpr(StartLoc, EndLoc, LSI);
     }
+    return inherited::RebuildLambdaExpr(StartLoc, EndLoc, LSI);
+  }
 
-    StmtResult TransformLambdaBody(LambdaExpr *E, Stmt *Body) {
-      // Currently, we instantiate the body when instantiating the lambda
-      // expression. However, `EvaluateConstraints` is disabled during the
-      // instantiation of the lambda expression, causing the instantiation
-      // failure of the return type requirement in the body. If p0588r1 is fully
-      // implemented, the body will be lazily instantiated, and this problem
-      // will not occur. Here, `EvaluateConstraints` is temporarily set to
-      // `true` to temporarily fix this issue.
-      // FIXME: This temporary fix can be removed after fully implementing
-      // p0588r1.
-      llvm::SaveAndRestore _(EvaluateConstraints, true);
-      return inherited::TransformLambdaBody(E, Body);
-    }
+  StmtResult TransformLambdaBody(LambdaExpr *E, Stmt *Body) {
+    // Currently, we instantiate the body when instantiating the lambda
+    // expression. However, `EvaluateConstraints` is disabled during the
+    // instantiation of the lambda expression, causing the instantiation
+    // failure of the return type requirement in the body. If p0588r1 is fully
+    // implemented, the body will be lazily instantiated, and this problem
+    // will not occur. Here, `EvaluateConstraints` is temporarily set to
+    // `true` to temporarily fix this issue.
+    // FIXME: This temporary fix can be removed after fully implementing
+    // p0588r1.
+    llvm::SaveAndRestore _(EvaluateConstraints, true);
+    return inherited::TransformLambdaBody(E, Body);
+  }
 
-    ExprResult TransformRequiresExpr(RequiresExpr *E) {
-      LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
-      ExprResult TransReq = inherited::TransformRequiresExpr(E);
-      if (TransReq.isInvalid())
-        return TransReq;
-      assert(TransReq.get() != E &&
-             "Do not change value of isSatisfied for the existing expression. "
-             "Create a new expression instead.");
-      if (E->getBody()->isDependentContext()) {
-        Sema::SFINAETrap Trap(SemaRef);
-        // We recreate the RequiresExpr body, but not by instantiating it.
-        // Produce pending diagnostics for dependent access check.
-        SemaRef.PerformDependentDiagnostics(E->getBody(), TemplateArgs);
-        // FIXME: Store SFINAE diagnostics in RequiresExpr for diagnosis.
-        if (Trap.hasErrorOccurred())
-          TransReq.getAs<RequiresExpr>()->setSatisfied(false);
-      }
+  ExprResult TransformRequiresExpr(RequiresExpr *E) {
+    LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
+    ExprResult TransReq = inherited::TransformRequiresExpr(E);
+    if (TransReq.isInvalid())
       return TransReq;
+    assert(TransReq.get() != E &&
+           "Do not change value of isSatisfied for the existing expression. "
+           "Create a new expression instead.");
+    if (E->getBody()->isDependentContext()) {
+      Sema::SFINAETrap Trap(SemaRef);
+      // We recreate the RequiresExpr body, but not by instantiating it.
+      // Produce pending diagnostics for dependent access check.
+      SemaRef.PerformDependentDiagnostics(E->getBody(), TemplateArgs);
+      // FIXME: Store SFINAE diagnostics in RequiresExpr for diagnosis.
+      if (Trap.hasErrorOccurred())
+        TransReq.getAs<RequiresExpr>()->setSatisfied(false);
     }
+    return TransReq;
+  }
 
-    bool TransformRequiresExprRequirements(
-        ArrayRef<concepts::Requirement *> Reqs,
-        SmallVectorImpl<concepts::Requirement *> &Transformed) {
-      bool SatisfactionDetermined = false;
-      for (concepts::Requirement *Req : Reqs) {
-        concepts::Requirement *TransReq = nullptr;
-        if (!SatisfactionDetermined) {
-          if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req))
-            TransReq = TransformTypeRequirement(TypeReq);
-          else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req))
-            TransReq = TransformExprRequirement(ExprReq);
-          else
-            TransReq = TransformNestedRequirement(
-                cast<concepts::NestedRequirement>(Req));
-          if (!TransReq)
-            return true;
-          if (!TransReq->isDependent() && !TransReq->isSatisfied())
-            // [expr.prim.req]p6
-            //   [...]  The substitution and semantic constraint checking
-            //   proceeds in lexical order and stops when a condition that
-            //   determines the result of the requires-expression is
-            //   encountered. [..]
-            SatisfactionDetermined = true;
-        } else
-          TransReq = Req;
-        Transformed.push_back(TransReq);
-      }
-      return false;
+  bool TransformRequiresExprRequirements(
+      ArrayRef<concepts::Requirement *> Reqs,
+      SmallVectorImpl<concepts::Requirement *> &Transformed) {
+    bool SatisfactionDetermined = false;
+    for (concepts::Requirement *Req : Reqs) {
+      concepts::Requirement *TransReq = nullptr;
+      if (!SatisfactionDetermined) {
+        if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req))
+          TransReq = TransformTypeRequirement(TypeReq);
+        else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req))
+          TransReq = TransformExprRequirement(ExprReq);
+        else
+          TransReq = TransformNestedRequirement(
+              cast<concepts::NestedRequirement>(Req));
+        if (!TransReq)
+          return true;
+        if (!TransReq->isDependent() && !TransReq->isSatisfied())
+          // [expr.prim.req]p6
+          //   [...]  The substitution and semantic constraint checking
+          //   proceeds in lexical order and stops when a condition that
+          //   determines the result of the requires-expression is
+          //   encountered. [..]
+          SatisfactionDetermined = true;
+      } else
+        TransReq = Req;
+      Transformed.push_back(TransReq);
     }
+    return false;
+  }
 
-    TemplateParameterList *TransformTemplateParameterList(
-                              TemplateParameterList *OrigTPL)  {
-      if (!OrigTPL || !OrigTPL->size()) return OrigTPL;
-
-      DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext();
-      TemplateDeclInstantiator  DeclInstantiator(getSema(),
-                        /* DeclContext *Owner */ Owner, TemplateArgs);
-      DeclInstantiator.setEvaluateConstraints(EvaluateConstraints);
-      return DeclInstantiator.SubstTemplateParams(OrigTPL);
-    }
+  TemplateParameterList *
+  TransformTemplateParameterList(TemplateParameterList *OrigTPL) {
+    if (!OrigTPL || !OrigTPL->size())
+      return OrigTPL;
+
+    DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext();
+    TemplateDeclInstantiator DeclInstantiator(getSema(),
+                                              /* DeclContext *Owner */ Owner,
+                                              TemplateArgs);
+    DeclInstantiator.setEvaluateConstraints(EvaluateConstraints);
+    return DeclInstantiator.SubstTemplateParams(OrigTPL);
+  }
 
-    concepts::TypeRequirement *
-    TransformTypeRequirement(concepts::TypeRequirement *Req);
-    concepts::ExprRequirement *
-    TransformExprRequirement(concepts::ExprRequirement *Req);
-    concepts::NestedRequirement *
-    TransformNestedRequirement(concepts::NestedRequirement *Req);
-    ExprResult TransformRequiresTypeParams(
-        SourceLocation KWLoc, SourceLocation RBraceLoc, const RequiresExpr *RE,
-        RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> Params,
-        SmallVectorImpl<QualType> &PTypes,
-        SmallVectorImpl<ParmVarDecl *> &TransParams,
-        Sema::ExtParameterInfoBuilder &PInfos);
-  };
-}
+  concepts::TypeRequirement *
+  TransformTypeRequirement(concepts::TypeRequirement *Req);
+  concepts::ExprRequirement *
+  TransformExprRequirement(concepts::ExprRequirement *Req);
+  concepts::NestedRequirement *
+  TransformNestedRequirement(concepts::NestedRequirement *Req);
+  ExprResult TransformRequiresTypeParams(
+      SourceLocation KWLoc, SourceLocation RBraceLoc, const RequiresExpr *RE,
+      RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> Params,
+      SmallVectorImpl<QualType> &PTypes,
+      SmallVectorImpl<ParmVarDecl *> &TransParams,
+      Sema::ExtParameterInfoBuilder &PInfos);
+};
+} // namespace
 
 bool TemplateInstantiator::AlreadyTransformed(QualType T) {
   if (T.isNull())
@@ -2767,8 +2765,8 @@ TemplateInstantiator::TransformNestedRequirement(
                                       Req->getConstraintSatisfaction());
     return Req;
   }
-  Sema::InstantiatingTemplate ReqInst(SemaRef,
-      Req->getConstraintExpr()->getBeginLoc(), Req,
+  Sema::InstantiatingTemplate ReqInst(
+      SemaRef, Req->getConstraintExpr()->getBeginLoc(), Req,
       Sema::InstantiatingTemplate::ConstraintsCheck{},
       Req->getConstraintExpr()->getSourceRange());
   if (!getEvaluateConstraints()) {
@@ -2790,8 +2788,8 @@ TemplateInstantiator::TransformNestedRequirement(
     EnterExpressionEvaluationContext ContextRAII(
         SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
     Sema::SFINAETrap Trap(SemaRef);
-    Sema::InstantiatingTemplate ConstrInst(SemaRef,
-        Req->getConstraintExpr()->getBeginLoc(), Req, Info,
+    Sema::InstantiatingTemplate ConstrInst(
+        SemaRef, Req->getConstraintExpr()->getBeginLoc(), Req, Info,
         Req->getConstraintExpr()->getSourceRange());
     if (ConstrInst.isInvalid())
       return nullptr;
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 696730148..ac9511467 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -5109,7 +5109,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(
       // all of the template arguments in the argument pack.
       typedef TemplateArgumentLocInventIterator<Derived,
                                                 TemplateArgument::pack_iterator>
-        PackLocIterator;
+          PackLocIterator;
       if (TransformTemplateArguments(
               PackLocIterator(*this, In.getArgument().pack_begin()),
               PackLocIterator(*this, In.getArgument().pack_end()), Outputs,
@@ -5179,7 +5179,6 @@ bool TreeTransform<Derived>::TransformTemplateArguments(
   }
 
   return false;
-
 }
 
 // FIXME: Find ways to reduce code duplication for pack expansions.
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 70b898a53..1c3999d69 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -807,7 +807,7 @@ readConstraintSatisfaction(ASTRecordReader &Record) {
   if (!Satisfaction.IsSatisfied) {
     unsigned NumDetailRecords = Record.readInt();
     for (unsigned i = 0; i != NumDetailRecords; ++i) {
-      if (/* IsDiagnostic */Record.readInt()) {
+      if (/* IsDiagnostic */ Record.readInt()) {
         SourceLocation DiagLocation = Record.readSourceLocation();
         StringRef DiagMessage = C.backupStr(Record.readString());
 

@cor3ntin cor3ntin merged commit 047f8c8 into main Oct 2, 2025
18 of 26 checks passed
@cor3ntin cor3ntin deleted the revert-141776-corentin/use_normalization_for_satisfaction branch October 2, 2025 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang Clang issues not falling into any other category HLSL HLSL Language Support libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants